﻿using System.ComponentModel;
using System.Windows;
using System.Windows.Input;

namespace Commands
{
    public class Closing
    {
        #region CommandProperty

        public static ICommand GetCommand(DependencyObject obj)
        {
            return (ICommand)obj.GetValue(CommandProperty);
        }

        public static void SetCommand(DependencyObject obj, ICommand value)
        {
            obj.SetValue(CommandProperty, value);
        }

        // Using a DependencyProperty as the backing store for Command.
        //This enables animation, styling, binding, etc...
        public static readonly DependencyProperty CommandProperty =
            DependencyProperty.RegisterAttached("Command", typeof(ICommand), typeof(Closing),
                new PropertyMetadata(CommandProperty_Changed));

        private static void CommandProperty_Changed(DependencyObject dependencyObject, DependencyPropertyChangedEventArgs e)
        {
            Window element = dependencyObject as Window;
            if (element != null)
            {
                ClosingBehavior behavior = GetOrCreateBehavior(element);
                behavior.Command = e.NewValue as ICommand;
            }
        }

        #endregion

        #region CommandParameterProperty

        public static readonly DependencyProperty CommandParameterProperty =
             DependencyProperty.RegisterAttached("CommandParameter", typeof(object),
                typeof(Closing), new PropertyMetadata(CommandParameterProperty_Changed));

        public static object GetCommandParameter(DependencyObject obj)
        {
            return obj.GetValue(CommandParameterProperty);
        }

        public static void SetCommandParameter(DependencyObject obj, object value)
        {
            obj.SetValue(CommandParameterProperty, value);
        }

        private static void CommandParameterProperty_Changed(DependencyObject dependencyObject, DependencyPropertyChangedEventArgs e)
        {
            Window element = dependencyObject as Window;

            if (element != null)
                GetOrCreateBehavior(element).CommandParameter = e.NewValue;
        }

        #endregion

        private static ClosingBehavior GetOrCreateBehavior(Window element)
        {
            ClosingBehavior behavior = element.GetValue(ClosingBehaviourProperty) as ClosingBehavior;
            if (behavior == null)
            {
                behavior = new ClosingBehavior(element);
                element.SetValue(ClosingBehaviourProperty, behavior);
            }

            return behavior;
        }

        public static ClosingBehavior GetClosingBehavior(DependencyObject obj)
        {
            return (ClosingBehavior)obj.GetValue(ClosingBehaviourProperty);
        }

        public static void SetClosingBehavior(DependencyObject obj,
            ClosingBehavior value)
        {
            obj.SetValue(ClosingBehaviourProperty, value);
        }

        // Using a DependencyProperty as the backing store for MouseOverCommandBehavior.
        //This enables animation, styling, binding, etc...
        public static readonly DependencyProperty ClosingBehaviourProperty =
            DependencyProperty.RegisterAttached("ClosingBehaviour",
                typeof(ClosingBehavior), typeof(Closing), null);
    }

    public class ClosingBehavior : CommandBehaviorBase<Window>
    {
        public ClosingBehavior(Window Window)
            : base(Window)
        {
            Window.Closing += new CancelEventHandler(Window_Closing);
        }

        void Window_Closing(object sender, CancelEventArgs e)
        {
            ClosingArgs args = new ClosingArgs()
            {
                Sender = sender
            };
            this.CommandParameter = args;
            base.ExecuteCommand();
        }
    }

    public class ClosingArgs
    {
        public object Sender { get; set; }
    }
}
